package contegor.scire.structure;

import java.io.File;
import java.io.IOException;

import contegor.scire.core.Container;
import contegor.scire.core.DuplicateElementException;
import contegor.scire.core.Id;
import contegor.scire.core.IdFragment;
import contegor.scire.core.MissingElementException;
import contegor.scire.core.ReturnPoint;
import contegor.scire.core.Task;
import contegor.scire.core.TransactionId;
import contegor.scire.core.WrongStateException;

/**
 * Persitent synchronous {@link ConceptCloud} implementation.
 *
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
public class FilesSynchronousConceptCloud extends AbstractConceptCloud {

  protected class FilesCloudRootContainerImpl extends CloudRootContainerImpl {
    private static final long serialVersionUID = -1695333811122756458L;

    public FilesCloudRootContainerImpl(long creationTime, TransactionId transactionId, IdFragment idFragment) {
      super(creationTime, transactionId, idFragment);
    }

    public <R> void route(Task<R> task, int commonAncestors, ReturnPoint<? super R> rp) {
      if (this.getId().sameRoot(task.getTargetContainerId()))
        super.route(task, commonAncestors, rp);
      else
        dock.submit(task, rp);
    }

    @Override
    public void incorporateContainer(Container container) throws DuplicateElementException, WrongStateException {
      if (!(container instanceof FilesContainer))
        throw new WrongStateException("Only FilesContainer can be added to this cloud.");
      if (this.identifiables.putIfAbsent(container.getLocalIdFragment(), container) != null)
        throw new DuplicateElementException("Trying to create a ContainerImpl with an Id allready in use: " + container.getLocalIdFragment());
      container.setContainer(this);
    }
  }

  private FilesSynchronousConceptCloud(IdFragment rootId) {
    super();
    this.root = new FilesCloudRootContainerImpl(System.currentTimeMillis(), null, rootId);
  }

  public FilesSynchronousConceptCloud(IdFragment rootId, File ... paths) throws DuplicateElementException, WrongStateException, IOException {
    this(rootId);
    for (File path: paths)
      this.root.incorporateContainer(new FilesContainer(path.getCanonicalPath(), path));
  }

  public FilesSynchronousConceptCloud(IdFragment rootId, String ... paths) throws DuplicateElementException, WrongStateException, IOException {
    this(rootId);
    for (String path: paths)
      this.root.incorporateContainer(new FilesContainer(path, path));
  }

  public FilesSynchronousConceptCloud(IdFragment rootId, FilesContainer ... containers) throws DuplicateElementException, WrongStateException, IOException {
    this(rootId);
    for (FilesContainer container: containers)
      this.root.incorporateContainer(container);
  }

  @Override
  public void createContainer(Id id) throws MissingElementException, DuplicateElementException {
    throw new UnsupportedOperationException();
  }


  @Override
  public <T> void process(Task<T> task, ReturnPoint<? super T> rp) {
    if (this.root.getId().sameRoot(task.getTargetContainerId())) {
      Container container = find(task.getTargetContainerId());
      if (container != null) {
        container.process(task, rp);
        return;
      }
    }
    rp.manage(task.getTaskId(), new MissingElementException("Can't find target container: " + task.getTargetContainerId()));
    rp.finish(task.getTaskId());
  }
}
